
package galaxy.app.network.websocket;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import galaxy.app.Galaxy;
import galaxy.app.log.LogHelper;
import galaxy.app.system.ConfigComponent;
import galaxy.kernel.Constants;
import galaxy.kernel.exception.CoreException;
import galaxy.kernel.system.AbstractECSSystem;

import java.io.File;

public class WebSocketServerSystem extends AbstractECSSystem {

    WebSocketServerComponent c;

    public WebSocketServerSystem() {
    }

    // public WebSocketServerSystem( ChannelHandler... handlers) {
    //     this( new WebSocketServerInitializer(handlers));
    // }

    // public WebSocketServerSystem( SslContext sslContext, ChannelHandler... handlers) {
    //     this(new WebSocketServerInitializer(sslContext, handlers));
    // }

    // public WebSocketServerSystem(  ChannelInitializer<SocketChannel> channelInitializer) {
    //     ConfigComponent config = Galaxy.components().getSingle(ConfigComponent.class);
    //     this.port = config.currentNode.getPort();
    //     this.channelInitializer = channelInitializer;
    // }

    @Override
    public void load(){
        c = Galaxy.components().getSingle(WebSocketServerComponent.class);
        if(c == null){
            return ;
        }

        ConfigComponent config = Galaxy.components().getSingle(ConfigComponent.class);
        c.port = config.currentNode.getPort();
        c.channelInitializer = new WebSocketServerInitializer(
                new WebSocketDecoder(),
                new WebSocketEncoder(),
                new WebSocketServerHandler()
        );
    }

    @Override
    public void start() {
        if(c == null){
            return ;
        }
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(c.bossGroup, c.workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(c.channelInitializer);

            Channel ch = bootstrap.bind(c.port).sync().channel();
            LogHelper.info(" ------> url : ws://127.0.0.1:{}", c.port);
            new Thread(() -> {
                try {
                    ch.closeFuture().sync();
                } catch (InterruptedException e) {
                    c.bossGroup.shutdownGracefully();
                    c.workerGroup.shutdownGracefully();
                }
            }).start();
        } catch (Exception e) {
            LogHelper.error("", e);
        }
    }

    @Override
    public void stop() {
        c.bossGroup.shutdownGracefully();
        c.workerGroup.shutdownGracefully();
    }

    // @Override
    // public String name() {
    //     return Constants.Net.WEB_SOCKET_SERVER;
    // }

    /**
     * @param filePath *.pem file
     * @param keyPath  *.key file
     * @return
     */
    public static SslContext createSSLContext(String filePath, String keyPath) {
        try {
            File file = new File(filePath);
            File key = new File(keyPath);

            SslContext sslCtx = SslContextBuilder.forServer(file, key).build();
            return sslCtx;
        } catch (Exception ex) {
            throw new CoreException("ssl context create fail. ", ex);
        }
    }
}